# -*- coding: utf-8 -*-
import base64
import logging
from os.path import join

import msgpack
import requests

from messagebroker.exception import MessageBrokerError
from messagebroker.json import json_dumps

logger = logging.getLogger('mb')


class MessageBrokerClient(object):

    MARSHAL_JSON = 'json'
    MARSHAL_MSGPACK = 'msgpack'

    FLAG_TEXT = 'text'
    FLAG_JSON = 'json'
    FLAG_MSGPACK = 'msgpack'

    def __init__(self, base_url, connection):
        self.base_url = base_url
        self.session = requests.Session()

        self.connection = connection

    def send_text(self, s, exchange, routing_key):
        """send text

        Args:
            :s: (str)
            :exchange: (str)
            :routing_key: (str)

        Returns:
            (bool) True if ok

        Raises:
            (MessageBorkerError)
        """
        b = s
        if isinstance(s, str):
            b = b.encode('UTF-8')
        return self.send(
            b,
            self.connection,
            exchange,
            routing_key,
            self.FLAG_TEXT,
        )

    def send_data(self, o, exchange, routing_key, marshal='json'):
        """send structured data

        Args:
            :o: (object)
            :exchange: (str)
            :routing_key: (str)
            :marshal: (str MARSHAL_*)

        Returns:
            (bool) True if ok

        Raises:
            (MessageBorkerError)
        """
        b = b''
        flag = self.FLAG_JSON
        if marshal == self.MARSHAL_JSON:
            b = json_dumps(o)
        elif marshal == self.MARSHAL_MSGPACK:
            b = msgpack.packb(o)
            flag = self.FLAG_MSGPACK
        else:
            raise MessageBrokerError('unknown marshal: %s' % marshal)

        return self.send(
            b,
            self.connection,
            exchange,
            routing_key,
            flag,
        )


    def send(self, b, connection, exchange, routing_key, flag):

        if not isinstance(b, bytes):
            raise MessageBrokerError('b must be bytes')

        if flag != self.FLAG_TEXT:
            b = base64.b64encode(b)

        data = {
            'connection': connection,
            'exchange': exchange,
            'routingKey': routing_key,
            'body': b,
            'flag': flag,
        }

        logger.debug('send with data: %s' % data)

        url = join(self.base_url, 'v1/send')

        try:
            resp = self.session.post(
                url,
                data=data
            )

            if resp.status_code == 200:
                return True
        except Exception as e:
            logger.exception('error when send')
            m = str(e)
            raise MessageBrokerError(m)
        raise MessageBrokerError('unknown error')


    def send_datav2(self, o, exchange, routing_key, headers,
                    properties, marshal='json'):
        """
        v2 版发送数据对象，会根据 marshal 类型进行编码

        Args:
            :o: 对象
            :exchange: str
            :routing_key: str
            :headers: dict
            :properties: dict
            :marshal: str MARSHAL_*
        """

        b = b''
        flag = self.FLAG_JSON
        if marshal == self.MARSHAL_JSON:
            b = json_dumps(o)
        elif marshal == self.MARSHAL_MSGPACK:
            b = msgpack.packb(o)
            flag = self.FLAG_MSGPACK
        else:
            raise MessageBrokerError('unknown marshal: %s' % marshal)

        return self.sendv2(
            b,
            connection=self.connection,
            exchange=exchange,
            routing_key=routing_key,
            flag=flag,
            headers=headers,
            properties=properties)


    def sendv2(self, b, connection, exchange,
               routing_key, flag, headers, properties):
        """
        v2 版发送

        Args:
            :b: bytes 二进制内容
            :connection: str
            :exchange: str
            :routing_key: str
            :flag: str FLAG_*
            :headers: dict
            :properties: dict
        """

        if not isinstance(b, bytes):
            raise MessageBrokerError('b must be bytes')

        if flag != self.FLAG_TEXT:
            b = base64.b64encode(b)

        data = {
            'connection': connection,
            'exchange': exchange,
            'routingKey': routing_key,
            'body': b.decode('utf-8'),
            'flag': flag,
            'headers': headers,
            'properties': properties,
        }

        logger.debug('send with data: %s' % data)

        url = join(self.base_url, 'v2/send')

        try:
            resp = self.session.post(
                url,
                headers={'Content-Type': 'application/json'},
                data=json_dumps(data),
            )

            if resp.status_code == 200:
                return True
        except Exception as e:
            logger.exception('error when send')
            m = str(e)
            raise MessageBrokerError(m)
        raise MessageBrokerError('unknown error')
